#pragma once

#ifndef __LIT__VECTOR__HH__
#define __LIT__VECTOR__HH__

#include <vector>

namespace Lit
{
	template<typename T>
	class LIT_API Vector
	{
	public:
		typename typedef std::vector<T>				vec_type;
		typename typedef vec_type::iterator			Itor;
		typename typedef vec_type::const_iterator	ConstItor;
		
		struct Listener
		{
			virtual void itemAdded( Itor& itor )
			{
			}
			virtual void itemRemoved( Itor& itor )
			{
			}
		};
		typedef std::vector<Listener*>		listener_vec_type;
	protected:
		vec_type d;
		listener_vec_type l;

	public:
		Vector(){}
		Vector( const Vector<T> & rk ){ d = rk.d; l=rk.l; }
		Vector( const vec_type & rk ){ d = rk; }
		~Vector(){ clear(); l.clear(); }

		bool hasListeners() const{ return !l.empty(); }
		bool hasListener( Listener * lst ) const
		{
			for( auto i=l.begin(); i!=l.end(); i++ ) if( (*i) == lst ) return true;
			return false;
		}
		void addListener( Listener * lst ){ 
			if( !hasListener(lst) )
				l.push_back( lst );
		}
		void removeListener( Listener*lst )
		{
			for( auto i=l.begin(); i!=l.end(); i++ ) if( (*i) == lst ){ l.erase(i); return ; }
		}
		Vector& operator=( const Vector<T>& rk ){ l=rk.l; d = rk.d; return *this; }

		Itor begin(){ return d.begin(); }
		Itor end(){ return d.end(); }
		ConstItor begin() const{ return d.begin(); }
		ConstItor end() const{ return d.end(); }

		size_t size() const{ return d.size(); }
		void clear(){ 
			for( auto i=d.begin(); i!=d.end(); i++ )
				for( auto j=l.begin(); j!=l.end(); j++ ) 
					if( (*j) ) 
						(*j)->itemRemoved( i );
			d.clear(); 
		}
		bool empty() const{ return d.empty(); }

		void erase( Itor & i )
		{
			if( i == d.end() ) return ;
			for( auto il=l.begin(); il!=l.end(); il++ ) if( (*il) ) (*il)->itemRemoved(i);
			d.erase( i );
		}
		size_t findId( const T &item ) const
		{
			size_t id=0;
			ConstItor i(d.end(); d.end();d.end())
			for( i; i.hasNext(); ++i )
				if( (*i) == item ) return id;
			return size_t(-1);
		}

		Itor find( T& item ){
			Itor i( d.begin() );
			while( i!=d.end() )
			{
				if( *i == item ) return i;
				i++;
			}
			return end();
		}
		ConstItor find( const T& item ) const
		{
			ConstItor i( d.begin() );
			while( i!=d.end() )
			{
				if( *i == item ) return i;
				i++;
			}
			return end();
		}
		void push( T& item ){
			if( find(item) != d.end() )
				throw std::runtime_error("item already pushed in vector !");
			d.push_back( item );

			Itor ci(find( item ));
			for( auto i=l.begin(); i!=l.end(); i++ ) if( (*i) ) (*i)->itemAdded( ci );
		}
		void pop( )
		{
			if( d.empty() )
				throw std::runtime_error( "vector empty" );
			ConstItor ci(find( item ));
			for( auto i=l.begin(); i!=l.end(); i++ ) if( (*i) ) (*i)->itemRemoved( ci );
			d.pop_back();
		}
		Vector<T>& operator << ( const T& item )
		{
			push( item );
			return *this;
		}
		Vector<T>& operator()( const T& item )
		{
			push( item );
			return *this;
		}
		T operator[]( size_t id ) const
		{
			assert( id < d.size() );
			return d.at(id);
		}

		T& at( size_t id ){ assert( id < d.size() ); return d.at(id); }
		const T at( size_t id ) const{ assert( id < d.size() ); return d.at(id); }
	};
};
#endif